/*
 * Copyright (C)
 * Copyright (C)
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or (at your
 * option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program. If not, see <http://www.gnu.org/licenses/>.
 */

/// \addtogroup world The World
/// @{
/// \file

#ifndef __WORLD_H
#define __WORLD_H

#include "Common.h"
#include "Timer.h"
#include <ace/Singleton.h>
#include <ace/Atomic_Op.h>
#include "SharedDefines.h"
#include "QueryResult.h"
#include "Callback.h"

#include <map>
#include <set>
#include <list>

class Object;
class WorldPacket;
class WorldSession;
class Player;
class WorldSocket;
class SystemMgr;

extern uint32 realmID;

// ServerMessages.dbc
enum ServerMessageType
{
	SERVER_MSG_SHUTDOWN_TIME = 1,
	SERVER_MSG_RESTART_TIME = 2,
	SERVER_MSG_STRING = 3,
	SERVER_MSG_SHUTDOWN_CANCELLED = 4,
	SERVER_MSG_RESTART_CANCELLED = 5
};

enum ShutdownMask
{
	SHUTDOWN_MASK_RESTART = 1,
	SHUTDOWN_MASK_IDLE = 2,
};

enum ShutdownExitCode
{
	SHUTDOWN_EXIT_CODE = 0,
	ERROR_EXIT_CODE = 1,
	RESTART_EXIT_CODE = 2,
};

/// Timers for different object refresh rates
enum WorldTimers
{
	WUPDATE_AUCTIONS,
	WUPDATE_WEATHERS,
	WUPDATE_CORPSES,
	WUPDATE_EVENTS,
	WUPDATE_CLEANDB,
	WUPDATE_AUTOBROADCAST,
	WUPDATE_MAILBOXQUEUE,
	WUPDATE_PINGDB,
	WUPDATE_5_SECS,
	WUPDATE_COUNT
};

/// Configuration elements
enum WorldBoolConfigs
{
	CONFIG_DURABILITY_LOSS_IN_PVP = 0,
	CROSSFACTION_SYSTEM_BATTLEGROUNDS,
	CONFIG_ADDON_CHANNEL,
	CONFIG_ALLOW_PLAYER_COMMANDS,
	CONFIG_CLEAN_CHARACTER_DB,
	CONFIG_STATS_SAVE_ONLY_ON_LOGOUT,
	CONFIG_ALLOW_TWO_SIDE_ACCOUNTS,
	CONFIG_ALLOW_TWO_SIDE_INTERACTION_CALENDAR,
	CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT,
	CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL,
	CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP,
	CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD,
	CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION,
	CONFIG_ALLOW_TWO_SIDE_INTERACTION_MAIL,
	CONFIG_ALLOW_TWO_SIDE_WHO_LIST,
	CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND,
	CONFIG_ALLOW_TWO_SIDE_TRADE,
	CONFIG_ALL_TAXI_PATHS,
	CONFIG_INSTANT_TAXI,
	CONFIG_INSTANCE_IGNORE_LEVEL,
	CONFIG_INSTANCE_IGNORE_RAID,
	CONFIG_GM_LOG_TRADE,
	CONFIG_ALLOW_GM_GROUP,
	CONFIG_ALLOW_GM_FRIEND,
	CONFIG_GM_LOWER_SECURITY,
	CONFIG_SKILL_PROSPECTING,
	CONFIG_SKILL_MILLING,
	CONFIG_SAVE_RESPAWN_TIME_IMMEDIATELY,
	CONFIG_WEATHER,
	CONFIG_ALWAYS_MAX_SKILL_FOR_LEVEL,
	CONFIG_QUEST_IGNORE_RAID,
	CONFIG_DETECT_POS_COLLISION,
	CONFIG_RESTRICTED_LFG_CHANNEL,
	CONFIG_SILENTLY_GM_JOIN_TO_CHANNEL,
	CONFIG_TALENTS_INSPECTING,
	CONFIG_CHAT_FAKE_MESSAGE_PREVENTING,
	CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVP,
	CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVE,
	CONFIG_DEATH_BONES_WORLD,
	CONFIG_DEATH_BONES_BG_OR_ARENA,
	CONFIG_DIE_COMMAND_MODE,
	CONFIG_DECLINED_NAMES_USED,
	CONFIG_BATTLEGROUND_CAST_DESERTER,
	CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE,
	CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY,
	CONFIG_BG_XP_FOR_KILL,
	CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS,
	CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE,
	CONFIG_ARENA_QUEUE_ANNOUNCER_PLAYERONLY,
	CONFIG_ARENA_SEASON_IN_PROGRESS,
	CONFIG_OFFHAND_CHECK_AT_SPELL_UNLEARN,
	CONFIG_VMAP_INDOOR_CHECK,
	CONFIG_PET_LOS,
	CONFIG_START_ALL_SPELLS,
	CONFIG_START_ALL_EXPLORED,
	CONFIG_START_ALL_REP,
	CONFIG_ALWAYS_MAXSKILL,
	CONFIG_PVP_TOKEN_ENABLE,
	CONFIG_NO_RESET_TALENT_COST,
	CONFIG_SHOW_KICK_IN_WORLD,
	CONFIG_AUTOBROADCAST,
	CONFIG_ALLOW_TICKETS,
	CONFIG_DBC_ENFORCE_ITEM_ATTRIBUTES,
	CONFIG_PRESERVE_CUSTOM_CHANNELS,
	CONFIG_WINTERGRASP_ENABLE,
	CONFIG_RANDOM_BG_ITEM_REW,
	CONFIG_ANTICHEAT_ENABLE,
	CONFIG_BAN_PLAYER,
	CONFIG_PDUMP_NO_PATHS,
	CONFIG_PDUMP_NO_OVERWRITE,
	CONFIG_FREE_DUAL_SPEC, // pussywizard
	CONFIG_ENABLE_MMAPS, // pussywizard
	CONFIG_ENABLE_LOGIN_AFTER_DC, // pussywizard
	CONFIG_DONT_CACHE_RANDOM_MOVEMENT_PATHS, // pussywizard
	CONFIG_QUEST_IGNORE_AUTO_ACCEPT,
	CONFIG_QUEST_IGNORE_AUTO_COMPLETE,
	CONFIG_WARDEN_ENABLED,
	BOOL_CONFIG_VALUE_COUNT
};

enum WorldFloatConfigs
{
	CONFIG_GROUP_XP_DISTANCE = 0,
	CONFIG_MAX_RECRUIT_A_FRIEND_DISTANCE,
	CONFIG_SIGHT_MONSTER,
	CONFIG_SIGHT_GUARDER,
	CONFIG_LISTEN_RANGE_SAY,
	CONFIG_LISTEN_RANGE_TEXTEMOTE,
	CONFIG_LISTEN_RANGE_YELL,
	CONFIG_CREATURE_FAMILY_FLEE_ASSISTANCE_RADIUS,
	CONFIG_CREATURE_FAMILY_ASSISTANCE_RADIUS,
	CONFIG_CHANCE_OF_GM_SURVEY,
	FLOAT_CONFIG_VALUE_COUNT
};

enum WorldIntConfigs
{
	CONFIG_COMPRESSION = 0,
	CONFIG_INTERVAL_MAPUPDATE,
	CONFIG_INTERVAL_CHANGEWEATHER,
	CONFIG_INTERVAL_DISCONNECT_TOLERANCE,
	CONFIG_PORT_WORLD,
	CONFIG_SOCKET_TIMEOUTTIME,
	CONFIG_SESSION_ADD_DELAY,
	CONFIG_GAME_TYPE,
	CONFIG_REALM_ZONE,
	CONFIG_STRICT_PLAYER_NAMES,
	CONFIG_STRICT_CHARTER_NAMES,
	CONFIG_STRICT_CHANNEL_NAMES,
	CONFIG_STRICT_PET_NAMES,
	CONFIG_MIN_PLAYER_NAME,
	CONFIG_MIN_CHARTER_NAME,
	CONFIG_MIN_PET_NAME,
	CONFIG_CHARACTER_CREATING_DISABLED,
	CONFIG_CHARACTER_CREATING_DISABLED_RACEMASK,
	CONFIG_CHARACTER_CREATING_DISABLED_CLASSMASK,
	CONFIG_CHARACTERS_PER_ACCOUNT,
	CONFIG_CHARACTERS_PER_REALM,
	CONFIG_HEROIC_CHARACTERS_PER_REALM,
	CONFIG_CHARACTER_CREATING_MIN_LEVEL_FOR_HEROIC_CHARACTER,
	CONFIG_SKIP_CINEMATICS,
	CONFIG_MAX_PLAYER_LEVEL,
	CONFIG_MIN_DUALSPEC_LEVEL,
	CONFIG_START_PLAYER_LEVEL,
	CONFIG_START_HEROIC_PLAYER_LEVEL,
	CONFIG_START_PLAYER_MONEY,
	CONFIG_MAX_HONOR_POINTS,
	CONFIG_START_HONOR_POINTS,
	CONFIG_MAX_ARENA_POINTS,
	CONFIG_START_ARENA_POINTS,
	CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL,
	CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL_DIFFERENCE,
	CONFIG_INSTANCE_RESET_TIME_HOUR,
	CONFIG_INSTANCE_RESET_TIME_RELATIVE_TIMESTAMP,
	CONFIG_INSTANCE_UNLOAD_DELAY,
	CONFIG_MAX_PRIMARY_TRADE_SKILL,
	CONFIG_MIN_PETITION_SIGNS,
	CONFIG_GM_LOGIN_STATE,
	CONFIG_GM_VISIBLE_STATE,
	CONFIG_GM_ACCEPT_TICKETS,
	CONFIG_GM_CHAT,
	CONFIG_GM_WHISPERING_TO,
	CONFIG_GM_LEVEL_IN_GM_LIST,
	CONFIG_GM_LEVEL_IN_WHO_LIST,
	CONFIG_START_GM_LEVEL,
	CONFIG_GROUP_VISIBILITY,
	CONFIG_MAIL_DELIVERY_DELAY,
	CONFIG_UPTIME_UPDATE,
	CONFIG_SKILL_CHANCE_ORANGE,
	CONFIG_SKILL_CHANCE_YELLOW,
	CONFIG_SKILL_CHANCE_GREEN,
	CONFIG_SKILL_CHANCE_GREY,
	CONFIG_SKILL_CHANCE_MINING_STEPS,
	CONFIG_SKILL_CHANCE_SKINNING_STEPS,
	CONFIG_SKILL_GAIN_CRAFTING,
	CONFIG_SKILL_GAIN_DEFENSE,
	CONFIG_SKILL_GAIN_GATHERING,
	CONFIG_SKILL_GAIN_WEAPON,
	CONFIG_MAX_OVERSPEED_PINGS,
	CONFIG_EXPANSION,
	CONFIG_CHATFLOOD_MESSAGE_COUNT,
	CONFIG_CHATFLOOD_MESSAGE_DELAY,
	CONFIG_CHATFLOOD_MUTE_TIME,
	CONFIG_EVENT_ANNOUNCE,
	CONFIG_CREATURE_FAMILY_ASSISTANCE_DELAY,
	CONFIG_CREATURE_FAMILY_FLEE_DELAY,
	CONFIG_WORLD_BOSS_LEVEL_DIFF,
	CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF,
	CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF,
	CONFIG_CHAT_STRICT_LINK_CHECKING_SEVERITY,
	CONFIG_CHAT_STRICT_LINK_CHECKING_KICK,
	CONFIG_CHAT_CHANNEL_LEVEL_REQ,
	CONFIG_CHAT_WHISPER_LEVEL_REQ,
	CONFIG_CHAT_SAY_LEVEL_REQ,
	CONFIG_TRADE_LEVEL_REQ,
	CONFIG_TICKET_LEVEL_REQ,
	CONFIG_AUCTION_LEVEL_REQ,
	CONFIG_MAIL_LEVEL_REQ,
	CONFIG_CORPSE_DECAY_NORMAL,
	CONFIG_CORPSE_DECAY_RARE,
	CONFIG_CORPSE_DECAY_ELITE,
	CONFIG_CORPSE_DECAY_RAREELITE,
	CONFIG_CORPSE_DECAY_WORLDBOSS,
	CONFIG_DEATH_SICKNESS_LEVEL,
	CONFIG_INSTANT_LOGOUT,
	CONFIG_DISABLE_BREATHING,
	CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER,
	CONFIG_BATTLEGROUND_PREMADE_GROUP_WAIT_FOR_MATCH,
	CONFIG_ARENA_MAX_RATING_DIFFERENCE,
	CONFIG_ARENA_RATING_DISCARD_TIMER,
	CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS,
	CONFIG_ARENA_SEASON_ID,
	CONFIG_ARENA_START_RATING,
	CONFIG_ARENA_START_PERSONAL_RATING,
	CONFIG_ARENA_START_MATCHMAKER_RATING,
	CONFIG_HONOR_AFTER_DUEL,
	CONFIG_PVP_TOKEN_MAP_TYPE,
	CONFIG_PVP_TOKEN_ID,
	CONFIG_PVP_TOKEN_COUNT,
	CONFIG_INTERVAL_LOG_UPDATE,
	CONFIG_MIN_LOG_UPDATE,
	CONFIG_ENABLE_SINFO_LOGIN,
	CONFIG_PLAYER_ALLOW_COMMANDS,
	CONFIG_NUMTHREADS,
	CONFIG_LOGDB_CLEARINTERVAL,
	CONFIG_TELEPORT_TIMEOUT_NEAR, // pussywizard
	CONFIG_TELEPORT_TIMEOUT_FAR, // pussywizard
	CONFIG_MAX_ALLOWED_MMR_DROP, // pussywizard
	CONFIG_CLIENTCACHE_VERSION,
	CONFIG_GUILD_EVENT_LOG_COUNT,
	CONFIG_GUILD_BANK_EVENT_LOG_COUNT,
	CONFIG_MIN_LEVEL_STAT_SAVE,
	CONFIG_RANDOM_BG_RESET_HOUR,
	CONFIG_GUILD_RESET_HOUR,
	CONFIG_CHARDELETE_KEEP_DAYS,
	CONFIG_CHARDELETE_METHOD,
	CONFIG_CHARDELETE_MIN_LEVEL,
	CONFIG_AUTOBROADCAST_CENTER,
	CONFIG_AUTOBROADCAST_INTERVAL,
	CONFIG_MAX_RESULTS_LOOKUP_COMMANDS,
	CONFIG_DB_PING_INTERVAL,
	CONFIG_PRESERVE_CUSTOM_CHANNEL_DURATION,
	CONFIG_PERSISTENT_CHARACTER_CLEAN_FLAGS,
	CONFIG_LFG_OPTIONSMASK,
	CONFIG_ANTICHEAT_REPORTS_INGAME_NOTIFICATION,
	CONFIG_ANTICHEAT_MAX_REPORTS_FOR_DAILY_REPORT,
	CONFIG_MAX_INSTANCES_PER_HOUR,
	CONFIG_ANTICHEAT_DETECTIONS_ENABLED,
	CONFIG_WINTERGRASP_PLR_MAX,
	CONFIG_WINTERGRASP_PLR_MIN,
	CONFIG_WINTERGRASP_PLR_MIN_LVL,
	CONFIG_WINTERGRASP_BATTLETIME,
	CONFIG_WINTERGRASP_NOBATTLETIME,
	CONFIG_WINTERGRASP_RESTART_AFTER_CRASH,
	CONFIG_RANDOM_BG_ITEM_ID,
	CONFIG_RANDOM_BG_WIN_COUNT,
	CONFIG_RANDOM_BG_LOS_COUNT,
	CONFIG_WARDEN_CLIENT_RESPONSE_DELAY,
	CONFIG_WARDEN_CLIENT_CHECK_HOLDOFF,
	CONFIG_WARDEN_CLIENT_FAIL_ACTION,
	CONFIG_WARDEN_CLIENT_BAN_DURATION,
	CONFIG_WARDEN_NUM_MEM_CHECKS,
	CONFIG_WARDEN_NUM_OTHER_CHECKS,
	CONFIG_BIRTHDAY_TIME,
	INT_CONFIG_VALUE_COUNT
};

/// Server rates
enum Rates
{
	RATE_HEALTH = 0,
	RATE_POWER_MANA,
	RATE_POWER_RAGE_INCOME,
	RATE_POWER_RAGE_LOSS,
	RATE_POWER_RUNICPOWER_INCOME,
	RATE_POWER_RUNICPOWER_LOSS,
	RATE_POWER_FOCUS,
	RATE_POWER_ENERGY,
	RATE_SKILL_DISCOVERY,
	RATE_DROP_ITEM_POOR,
	RATE_DROP_ITEM_NORMAL,
	RATE_DROP_ITEM_UNCOMMON,
	RATE_DROP_ITEM_RARE,
	RATE_DROP_ITEM_EPIC,
	RATE_DROP_ITEM_LEGENDARY,
	RATE_DROP_ITEM_ARTIFACT,
	RATE_DROP_ITEM_REFERENCED,
	RATE_DROP_ITEM_REFERENCED_AMOUNT,
	RATE_DROP_MONEY,
	RATE_XP_KILL,
	RATE_XP_QUEST,
	RATE_XP_EXPLORE,
	RATE_REPAIRCOST,
	RATE_REPUTATION_GAIN,
	RATE_REPUTATION_LOWLEVEL_KILL,
	RATE_REPUTATION_LOWLEVEL_QUEST,
	RATE_REPUTATION_RECRUIT_A_FRIEND_BONUS,
	RATE_CREATURE_NORMAL_HP,
	RATE_CREATURE_ELITE_ELITE_HP,
	RATE_CREATURE_ELITE_RAREELITE_HP,
	RATE_CREATURE_ELITE_WORLDBOSS_HP,
	RATE_CREATURE_ELITE_RARE_HP,
	RATE_CREATURE_NORMAL_DAMAGE,
	RATE_CREATURE_ELITE_ELITE_DAMAGE,
	RATE_CREATURE_ELITE_RAREELITE_DAMAGE,
	RATE_CREATURE_ELITE_WORLDBOSS_DAMAGE,
	RATE_CREATURE_ELITE_RARE_DAMAGE,
	RATE_CREATURE_NORMAL_SPELLDAMAGE,
	RATE_CREATURE_ELITE_ELITE_SPELLDAMAGE,
	RATE_CREATURE_ELITE_RAREELITE_SPELLDAMAGE,
	RATE_CREATURE_ELITE_WORLDBOSS_SPELLDAMAGE,
	RATE_CREATURE_ELITE_RARE_SPELLDAMAGE,
	RATE_CREATURE_AGGRO,
	RATE_REST_INGAME,
	RATE_REST_OFFLINE_IN_TAVERN_OR_CITY,
	RATE_REST_OFFLINE_IN_WILDERNESS,
	RATE_DAMAGE_FALL,
	RATE_AUCTION_TIME,
	RATE_AUCTION_DEPOSIT,
	RATE_AUCTION_CUT,
	RATE_HONOR,
	RATE_TALENT,
	RATE_CORPSE_DECAY_LOOTED,
	RATE_INSTANCE_RESET_TIME,
	RATE_TARGET_POS_RECALCULATION_RANGE,
	RATE_DURABILITY_LOSS_ON_DEATH,
	RATE_DURABILITY_LOSS_DAMAGE,
	RATE_DURABILITY_LOSS_PARRY,
	RATE_DURABILITY_LOSS_ABSORB,
	RATE_DURABILITY_LOSS_BLOCK,
	RATE_MOVESPEED,
	MAX_RATES
};

/// Can be used in SMSG_AUTH_RESPONSE packet
enum BillingPlanFlags
{
	SESSION_NONE = 0x00,
	SESSION_UNUSED = 0x01,
	SESSION_RECURRING_BILL = 0x02,
	SESSION_FREE_TRIAL = 0x04,
	SESSION_IGR = 0x08,
	SESSION_USAGE = 0x10,
	SESSION_TIME_MIXTURE = 0x20,
	SESSION_RESTRICTED = 0x40,
	SESSION_ENABLE_CAIS = 0x80,
};

/// Type of server, this is values from second column of Cfg_Configs.dbc
enum RealmType
{
	REALM_TYPE_NORMAL = 0,
	REALM_TYPE_PVP = 1,
	REALM_TYPE_NORMAL2 = 4,
	REALM_TYPE_RP = 6,
	REALM_TYPE_RPPVP = 8,
	REALM_TYPE_FFA_PVP = 16                                 // custom, free for all pvp mode like arena PvP in all zones except rest activated places and sanctuaries
	// replaced by REALM_PVP in realm list
};

enum RealmZone
{
	REALM_ZONE_UNKNOWN = 0,                           // any language
	REALM_ZONE_DEVELOPMENT = 1,                           // any language
	REALM_ZONE_UNITED_STATES = 2,                           // extended-Latin
	REALM_ZONE_OCEANIC = 3,                           // extended-Latin
	REALM_ZONE_LATIN_AMERICA = 4,                           // extended-Latin
	REALM_ZONE_TOURNAMENT_5 = 5,                           // basic-Latin at create, any at login
	REALM_ZONE_KOREA = 6,                           // East-Asian
	REALM_ZONE_TOURNAMENT_7 = 7,                           // basic-Latin at create, any at login
	REALM_ZONE_ENGLISH = 8,                           // extended-Latin
	REALM_ZONE_GERMAN = 9,                           // extended-Latin
	REALM_ZONE_FRENCH = 10,                          // extended-Latin
	REALM_ZONE_SPANISH = 11,                          // extended-Latin
	REALM_ZONE_RUSSIAN = 12,                          // Cyrillic
	REALM_ZONE_TOURNAMENT_13 = 13,                          // basic-Latin at create, any at login
	REALM_ZONE_TAIWAN = 14,                          // East-Asian
	REALM_ZONE_TOURNAMENT_15 = 15,                          // basic-Latin at create, any at login
	REALM_ZONE_CHINA = 16,                          // East-Asian
	REALM_ZONE_CN1 = 17,                          // basic-Latin at create, any at login
	REALM_ZONE_CN2 = 18,                          // basic-Latin at create, any at login
	REALM_ZONE_CN3 = 19,                          // basic-Latin at create, any at login
	REALM_ZONE_CN4 = 20,                          // basic-Latin at create, any at login
	REALM_ZONE_CN5 = 21,                          // basic-Latin at create, any at login
	REALM_ZONE_CN6 = 22,                          // basic-Latin at create, any at login
	REALM_ZONE_CN7 = 23,                          // basic-Latin at create, any at login
	REALM_ZONE_CN8 = 24,                          // basic-Latin at create, any at login
	REALM_ZONE_TOURNAMENT_25 = 25,                          // basic-Latin at create, any at login
	REALM_ZONE_TEST_SERVER = 26,                          // any language
	REALM_ZONE_TOURNAMENT_27 = 27,                          // basic-Latin at create, any at login
	REALM_ZONE_QA_SERVER = 28,                          // any language
	REALM_ZONE_CN9 = 29,                          // basic-Latin at create, any at login
	REALM_ZONE_TEST_SERVER_2 = 30,                          // any language
	REALM_ZONE_CN10 = 31,                          // basic-Latin at create, any at login
	REALM_ZONE_CTC = 32,
	REALM_ZONE_CNC = 33,
	REALM_ZONE_CN1_4 = 34,                          // basic-Latin at create, any at login
	REALM_ZONE_CN2_6_9 = 35,                          // basic-Latin at create, any at login
	REALM_ZONE_CN3_7 = 36,                          // basic-Latin at create, any at login
	REALM_ZONE_CN5_8 = 37                           // basic-Latin at create, any at login
};

enum WorldStates
{
	WS_WEEKLY_QUEST_RESET_TIME = 20002,                     // Next weekly reset time
	WS_BG_DAILY_RESET_TIME = 20003,                     // Next daily BG reset time
	WS_CLEANING_FLAGS = 20004,                     // Cleaning Flags
	WS_DAILY_QUEST_RESET_TIME = 20005,                     // pussywizard
	WS_GUILD_DAILY_RESET_TIME = 20006,                     // Next guild cap reset time
	WS_MONTHLY_QUEST_RESET_TIME = 20007,                     // Next monthly reset time
};

/// Storage class for commands issued for delayed execution
struct CliCommandHolder
{
	typedef void Print(void*, const char*);
	typedef void CommandFinished(void*, bool success);

	void* m_callbackArg;
	char *m_command;
	Print* m_print;

	CommandFinished* m_commandFinished;

	CliCommandHolder(void* callbackArg, const char *command, Print* zprint, CommandFinished* commandFinished)
		: m_callbackArg(callbackArg), m_print(zprint), m_commandFinished(commandFinished)
	{
		size_t len = strlen(command) + 1;
		m_command = new char[len];
		memcpy(m_command, command, len);
	}

	~CliCommandHolder() { delete[] m_command; }
};

typedef UNORDERED_MAP<uint32, WorldSession*> SessionMap;

#define WORLD_SLEEP_CONST 10

// xinef: global storage
struct GlobalPlayerData
{
	uint32 guidLow;
	uint32 accountId;
	std::string name;
	uint8 race;
	uint8 playerClass;
	uint8 gender;
	uint8 level;
	uint16 mailCount;
	uint32 guildId;
	uint32 groupId;
	uint32 arenaTeamId[3];
};

enum GlobalPlayerUpdateMask
{
	PLAYER_UPDATE_DATA_LEVEL = 0x01,
	PLAYER_UPDATE_DATA_RACE = 0x02,
	PLAYER_UPDATE_DATA_CLASS = 0x04,
	PLAYER_UPDATE_DATA_GENDER = 0x08,
	PLAYER_UPDATE_DATA_NAME = 0x10,
};

typedef UNORDERED_MAP<uint32, GlobalPlayerData> GlobalPlayerDataMap;
typedef std::map<std::string, uint32> GlobalPlayerNameMap;

// xinef: petitions storage
struct PetitionData
{
};

/// The World
class World
{
public:
	static uint32 m_worldLoopCounter;

	World();
	~World();

	WorldSession* FindSession(uint32 id) const;
	WorldSession* FindOfflineSession(uint32 id) const;
	WorldSession* FindOfflineSessionForCharacterGUID(uint32 guidLow) const;
	void AddSession(WorldSession* s);
	void SendAutoBroadcast();
	bool KickSession(uint32 id);
	/// Get the number of current active sessions
	void UpdateMaxSessionCounters();
	const SessionMap& GetAllSessions() const { return m_sessions; }
	uint32 GetActiveAndQueuedSessionCount() const { return m_sessions.size(); }
	uint32 GetActiveSessionCount() const { return m_sessions.size() - m_QueuedPlayer.size(); }
	uint32 GetQueuedSessionCount() const { return m_QueuedPlayer.size(); }
	/// Get the maximum number of parallel sessions on the server since last reboot
	uint32 GetMaxQueuedSessionCount() const { return m_maxQueuedSessionCount; }
	uint32 GetMaxActiveSessionCount() const { return m_maxActiveSessionCount; }
	/// Get number of players
	inline uint32 GetPlayerCount() const { return m_PlayerCount; }
	inline uint32 GetMaxPlayerCount() const { return m_MaxPlayerCount; }

	/// Increase/Decrease number of players
	inline void IncreasePlayerCount()
	{
		m_PlayerCount++;
		m_MaxPlayerCount = std::max(m_MaxPlayerCount, m_PlayerCount);
	}
	inline void DecreasePlayerCount() { m_PlayerCount--; }

	Player* FindPlayerInZone(uint32 zone);

	/// Deny clients?
	bool IsClosed() const;

	/// Close world
	void SetClosed(bool val);

	/// Security level limitations
	AccountTypes GetPlayerSecurityLimit() const { return m_allowedSecurityLevel; }
	void SetPlayerSecurityLimit(AccountTypes sec);
	void LoadDBAllowedSecurityLevel();

	/// Active session server limit
	void SetPlayerAmountLimit(uint32 limit) { m_playerLimit = limit; }
	uint32 GetPlayerAmountLimit() const { return m_playerLimit; }

	//player Queue
	typedef std::list<WorldSession*> Queue;
	void AddQueuedPlayer(WorldSession*);
	bool RemoveQueuedPlayer(WorldSession* session);
	int32 GetQueuePos(WorldSession*);
	bool HasRecentlyDisconnected(WorldSession*);

	/// \todo Actions on m_allowMovement still to be implemented
	/// Is movement allowed?
	bool getAllowMovement() const { return m_allowMovement; }
	/// Allow/Disallow object movements
	void SetAllowMovement(bool allow) { m_allowMovement = allow; }

	/// Set a new Message of the Day
	void SetMotd(std::string const& motd);
	/// Get the current Message of the Day
	const char* GetMotd() const;

	/// Set the string for new characters (first login)
	void SetNewCharString(std::string const& str) { m_newCharString = str; }
	/// Get the string for new characters (first login)
	std::string const& GetNewCharString() const { return m_newCharString; }

	LocaleConstant GetDefaultDbcLocale() const { return m_defaultDbcLocale; }

	/// Get the path where data (dbc, maps) are stored on disk
	std::string const& GetDataPath() const { return m_dataPath; }

	/// When server started?
	time_t const& GetStartTime() const { return m_startTime; }
	/// What time is it?
	time_t const& GetGameTime() const { return m_gameTime; }
	/// What time is it? in ms
	static uint32 GetGameTimeMS() { return m_gameMSTime; }
	/// Uptime (in secs)
	uint32 GetUptime() const { return uint32(m_gameTime - m_startTime); }
	/// Update time
	uint32 GetUpdateTime() const { return m_updateTime; }
	void SetRecordDiffInterval(int32 t) { if (t >= 0) m_int_configs[CONFIG_INTERVAL_LOG_UPDATE] = (uint32)t; }

	/// Next daily quests and random bg reset time
	time_t GetNextDailyQuestsResetTime() const { return m_NextDailyQuestReset; }
	time_t GetNextWeeklyQuestsResetTime() const { return m_NextWeeklyQuestReset; }
	time_t GetNextRandomBGResetTime() const { return m_NextRandomBGReset; }

	/// Get the maximum skill level a player can reach
	uint16 GetConfigMaxSkillValue() const
	{
		uint16 lvl = uint16(getIntConfig(CONFIG_MAX_PLAYER_LEVEL));
		return lvl > 60 ? 300 + ((lvl - 60) * 75) / 10 : lvl * 5;
	}

	void SetInitialWorldSettings();
	void LoadConfigSettings(bool reload = false);

	void SendWorldText(int32 string_id, ...);
	void SendGlobalText(const char* text, WorldSession* self);
	void SendGMText(int32 string_id, ...);
	void SendGlobalMessage(WorldPacket* packet, WorldSession* self = 0, TeamId teamId = TEAM_NEUTRAL);
	void SendGlobalGMMessage(WorldPacket* packet, WorldSession* self = 0, TeamId teamId = TEAM_NEUTRAL);
	bool SendZoneMessage(uint32 zone, WorldPacket* packet, WorldSession* self = 0, TeamId teamId = TEAM_NEUTRAL);
	void SendZoneText(uint32 zone, const char *text, WorldSession* self = 0, TeamId teamId = TEAM_NEUTRAL);
	void SendServerMessage(ServerMessageType type, const char *text = "", Player* player = NULL);

	/// Are we in the middle of a shutdown?
	bool IsShuttingDown() const { return m_ShutdownTimer > 0; }
	uint32 GetShutDownTimeLeft() const { return m_ShutdownTimer; }
	void ShutdownServ(uint32 time, uint32 options, uint8 exitcode);
	void ShutdownCancel();
	void ShutdownMsg(bool show = false, Player* player = NULL);
	static uint8 GetExitCode() { return m_ExitCode; }
	static void StopNow(uint8 exitcode) { m_stopEvent = true; m_ExitCode = exitcode; }
	static bool IsStopped() { return m_stopEvent.value(); }

	void Update(uint32 diff);

	void UpdateSessions(uint32 diff);
	/// Set a server rate (see #Rates)
	void setRate(Rates rate, float value) { rate_values[rate] = value; }
	/// Get a server rate (see #Rates)
	float getRate(Rates rate) const { return rate_values[rate]; }

	/// Set a server configuration element (see #WorldConfigs)
	void setBoolConfig(WorldBoolConfigs index, bool value)
	{
		if (index < BOOL_CONFIG_VALUE_COUNT)
			m_bool_configs[index] = value;
	}

	/// Get a server configuration element (see #WorldConfigs)
	bool getBoolConfig(WorldBoolConfigs index) const
	{
		return index < BOOL_CONFIG_VALUE_COUNT ? m_bool_configs[index] : 0;
	}

	/// Set a server configuration element (see #WorldConfigs)
	void setFloatConfig(WorldFloatConfigs index, float value)
	{
		if (index < FLOAT_CONFIG_VALUE_COUNT)
			m_float_configs[index] = value;
	}

	/// Get a server configuration element (see #WorldConfigs)
	float getFloatConfig(WorldFloatConfigs index) const
	{
		return index < FLOAT_CONFIG_VALUE_COUNT ? m_float_configs[index] : 0;
	}

	/// Set a server configuration element (see #WorldConfigs)
	void setIntConfig(WorldIntConfigs index, uint32 value)
	{
		if (index < INT_CONFIG_VALUE_COUNT)
			m_int_configs[index] = value;
	}

	/// Get a server configuration element (see #WorldConfigs)
	uint32 getIntConfig(WorldIntConfigs index) const
	{
		return index < INT_CONFIG_VALUE_COUNT ? m_int_configs[index] : 0;
	}

	void setWorldState(uint32 index, uint64 value);
	uint64 getWorldState(uint32 index) const;
	void LoadWorldStates();

	/// Are we on a "Player versus Player" server?
	bool IsPvPRealm() const { return (getIntConfig(CONFIG_GAME_TYPE) == REALM_TYPE_PVP || getIntConfig(CONFIG_GAME_TYPE) == REALM_TYPE_RPPVP || getIntConfig(CONFIG_GAME_TYPE) == REALM_TYPE_FFA_PVP); }
	bool IsFFAPvPRealm() const { return getIntConfig(CONFIG_GAME_TYPE) == REALM_TYPE_FFA_PVP; }

	void KickAll();
	void KickAllLess(AccountTypes sec);
	BanReturn BanAccount(BanMode mode, std::string const& nameOrIP, std::string const& duration, std::string const& reason, std::string const& author);
	bool RemoveBanAccount(BanMode mode, std::string const& nameOrIP);
	BanReturn BanCharacter(std::string const& name, std::string const& duration, std::string const& reason, std::string const& author);
	bool RemoveBanCharacter(std::string const& name);

	// for max speed access
	static float GetMaxVisibleDistanceOnContinents()    { return m_MaxVisibleDistanceOnContinents; }
	static float GetMaxVisibleDistanceInInstances()     { return m_MaxVisibleDistanceInInstances; }
	static float GetMaxVisibleDistanceInBGArenas()      { return m_MaxVisibleDistanceInBGArenas; }

	// our: needed for arena spectator subscriptions
	uint32 GetNextWhoListUpdateDelaySecs()
	{
		if (m_timers[WUPDATE_5_SECS].Passed())
			return 1;
		uint32 t = m_timers[WUPDATE_5_SECS].GetInterval() - m_timers[WUPDATE_5_SECS].GetCurrent();
		t = std::min(t, (uint32)m_timers[WUPDATE_5_SECS].GetInterval());
		return uint32(ceil(t / 1000.0f));
	}

	// xinef: Global Player Data Storage system
	void LoadGlobalPlayerDataStore();
	uint32 GetGlobalPlayerGUID(std::string const& name) const;
	GlobalPlayerData const* GetGlobalPlayerData(uint32 guid) const;
	void AddGlobalPlayerData(uint32 guid, uint32 accountId, std::string const& name, uint8 gender, uint8 race, uint8 playerClass, uint8 level, uint16 mailCount, uint32 guildId);
	void UpdateGlobalPlayerData(uint32 guid, uint8 mask, std::string const& name, uint8 level = 0, uint8 gender = 0, uint8 race = 0, uint8 playerClass = 0);
	void UpdateGlobalPlayerMails(uint32 guid, int16 count, bool add = true);
	void UpdateGlobalPlayerGuild(uint32 guid, uint32 guildId);
	void UpdateGlobalPlayerGroup(uint32 guid, uint32 groupId);
	void UpdateGlobalPlayerArenaTeam(uint32 guid, uint8 slot, uint32 arenaTeamId);
	void UpdateGlobalNameData(uint32 guidLow, std::string const& oldName, std::string const& newName);
	void DeleteGlobalPlayerData(uint32 guid, std::string const& name);

	void ProcessCliCommands();
	void QueueCliCommand(CliCommandHolder* commandHolder) { cliCmdQueue.add(commandHolder); }

	void ForceGameEventUpdate();

	void UpdateRealmCharCount(uint32 accid);

	// used World DB version
	void LoadDBVersion();
	char const* GetDBVersion() const { return m_DBVersion.c_str(); }
	void LoadAutobroadcasts();

	void UpdateAreaDependentAuras();

	uint32 GetCleaningFlags() const { return m_CleaningFlags; }
	void   SetCleaningFlags(uint32 flags) { m_CleaningFlags = flags; }
	void   ResetEventSeasonalQuests(uint16 event_id);

	time_t GetNextTimeWithDayAndHour(int8 dayOfWeek, int8 hour); // pussywizard
	time_t GetNextTimeWithMonthAndHour(int8 month, int8 hour); // pussywizard

	std::string const& GetRealmName() const { return _realmName; } // pussywizard
	void SetRealmName(std::string name) { _realmName = name; } // pussywizard

protected:
	void _UpdateGameTime();
	// callback for UpdateRealmCharacters
	void _UpdateRealmCharCount(PreparedQueryResult resultCharCount);

	void InitDailyQuestResetTime();
	void InitWeeklyQuestResetTime();
	void InitMonthlyQuestResetTime();
	void InitRandomBGResetTime();
	void InitGuildResetTime();
	void ResetDailyQuests();
	void ResetWeeklyQuests();
	void ResetMonthlyQuests();
	void ResetRandomBG();
	void ResetGuildCap();
private:
	static ACE_Atomic_Op<ACE_Thread_Mutex, bool> m_stopEvent;
	static uint8 m_ExitCode;
	uint32 m_ShutdownTimer;
	uint32 m_ShutdownMask;

	uint32 m_CleaningFlags;

	bool m_isClosed;

	time_t m_startTime;
	time_t m_gameTime;
	IntervalTimer m_timers[WUPDATE_COUNT];
	time_t mail_expire_check_timer;
	uint32 m_updateTime, m_updateTimeSum;
	static uint32 m_gameMSTime;

	SessionMap m_sessions;
	SessionMap m_offlineSessions;
	typedef UNORDERED_MAP<uint32, time_t> DisconnectMap;
	DisconnectMap m_disconnects;
	uint32 m_maxActiveSessionCount;
	uint32 m_maxQueuedSessionCount;
	uint32 m_PlayerCount;
	uint32 m_MaxPlayerCount;

	std::string m_newCharString;

	float rate_values[MAX_RATES];
	uint32 m_int_configs[INT_CONFIG_VALUE_COUNT];
	bool m_bool_configs[BOOL_CONFIG_VALUE_COUNT];
	float m_float_configs[FLOAT_CONFIG_VALUE_COUNT];
	typedef std::map<uint32, uint64> WorldStatesMap;
	WorldStatesMap m_worldstates;
	uint32 m_playerLimit;
	AccountTypes m_allowedSecurityLevel;
	LocaleConstant m_defaultDbcLocale;                     // from config for one from loaded DBC locales
	uint32 m_availableDbcLocaleMask;                       // by loaded DBC
	void DetectDBCLang();
	bool m_allowMovement;
	std::string m_motd;
	std::string m_dataPath;

	// for max speed access
	static float m_MaxVisibleDistanceOnContinents;
	static float m_MaxVisibleDistanceInInstances;
	static float m_MaxVisibleDistanceInBGArenas;

	// our speed ups
	GlobalPlayerDataMap _globalPlayerDataStore; // xinef
	GlobalPlayerNameMap _globalPlayerNameStore; // xinef

	std::string _realmName;

	// CLI command holder to be thread safe
	ACE_Based::LockedQueue<CliCommandHolder*, ACE_Thread_Mutex> cliCmdQueue;

	// next daily quests and random bg reset time
	time_t m_NextDailyQuestReset;
	time_t m_NextWeeklyQuestReset;
	time_t m_NextMonthlyQuestReset;
	time_t m_NextRandomBGReset;
	time_t m_NextGuildReset;

	//Player Queue
	Queue m_QueuedPlayer;

	// sessions that are added async
	void AddSession_(WorldSession* s);
	ACE_Based::LockedQueue<WorldSession*, ACE_Thread_Mutex> addSessQueue;

	// used versions
	std::string m_DBVersion;

	typedef std::map<uint8, std::string> AutobroadcastsMap;
	AutobroadcastsMap m_Autobroadcasts;

	typedef std::map<uint8, uint8> AutobroadcastsWeightMap;
	AutobroadcastsWeightMap m_AutobroadcastsWeights;

	void ProcessQueryCallbacks();
	ACE_Future_Set<PreparedQueryResult> m_realmCharCallbacks;
};

#define sWorld ACE_Singleton<World, ACE_Null_Mutex>::instance()
#endif
/// @}
